const { reject } = require("lodash");

// 状态常量
const PENDING = 'panding'; // 等待
const FULFILLED = 'fulfilled'; // 成功
const REJECTED = 'rejected'; // 失败



class myPromise {
    // 构造函数
    constructor(executor) {
        // 捕捉异常
        try {
            executor(this.resolve, this.reject) // 赋值回调函数
        } catch (e) {
            this.reject(e);
        }
    }
    // promise 状态
    // 一旦状态该改变，不可改变
    status = PENDING;
    // 成功之后的值
    value = undefined;
    // 失败之后的原因
    reason = undefined;
    // 成功回调函数
    successCallback = [];
    // 失败回调函数
    failCallback = [];

    resolve = value => {
        //如果状态不是等待，就向下执行
        if (this.status !== PENDING) { return; }
        // 状态改为成功
        this.status = FULFILLED;
        // 存储成功原因
        this.value = value;
        // 判断成功回调是否存在
        // this.successCallback && this.successCallback(this.value)
        // 连续调用then函数时
        while (this.successCallback.length) {
            this.successCallback.shift()(this.value)
        }

    }
    // 失败回调函数
    reject = reason => {
        // 状态改为失败
        this.status = REJECTED;
        // 存储失败 原因
        this.reason = reason;
        // 判断失败回调是否存在
        // this.failCallback && this.failCallback(this.reason)
        // 连续调用then函数时
        while (this.failCallback.length) {
            this.failCallback.shift()(this.value)
        }

    }
    // 判断状态，
    then(successCallback, failCallback) {

        // 参数可选
        successCallback = successCallback ? successCallback : value => value;
        // 参数可选
        failCallback = failCallback ? failCallback : reason => { throw reason };

        let promise2 = new myPromise((resolve, reject) => {

            // 判断状态
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = successCallback(this.value)
                        // resolve(x)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e);
                    }
                }, 0);
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    // 捕捉异常
                    try {
                        let x = failCallback(this.reason);
                        // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve 
                        // 如果是promise对象 查看promsie对象返回的结果 
                        // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                        resolvePromise(promsie2, x, resolve, reject)
                    } catch (e) {
                        reject(e);
                    }
                }, 0)
            } else {
                // // 处理异步函数
                // // 等待
                // // 将成功的回调函数和失败的回调函数存储起来
                // // this.successCallback  = successCallback
                // this.successCallback.push(successCallback)
                // // this.failCallback  = failCallback
                // this.failCallback.push(failCallback)
                // try {
                //     let x = successCallback(this.value);
                //     // 判断 x 的值是普通值还是promise对象
                //     // 如果是普通值 直接调用resolve 
                //     // 如果是promise对象 查看promsie对象返回的结果 
                //     // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                //     resolvePromise(promsie2, x, resolve, reject)
                // } catch (e) {
                //     reject(e);
                // }
                // 等待
                // 将成功回调和失败回调存储起来
                this.successCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = successCallback(this.value);
                            // 判断 x 的值是普通值还是promise对象
                            // 如果是普通值 直接调用resolve 
                            // 如果是promise对象 查看promsie对象返回的结果 
                            // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                            resolvePromise(promsie2, x, resolve, reject)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                });
                this.failCallback.push(() => {
                    // setTimeout(() => {
                    //   try {
                    //     let x = failCallback(this.reason);
                    // 判断 x 的值是普通值还是promise对象
                    // 如果是普通值 直接调用resolve 
                    // 如果是promise对象 查看promsie对象返回的结果 
                    // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                    resolvePromise(promsie2, x, resolve, reject)
                    //   }catch (e) {
                    //     reject(e);
                    //   }
                    // }, 0)
                });

            }
        });
        return promise2;
    }
    // 作用：允许我们通过异步任务调用的顺序，获取调用的结果
    // 可以传promise对象，也可以传值
    // 由于是类的方法，所以是个静态方法
    // 注意，一旦有一个异步任务是失败的，那么最终结果就是失败的
    static all (array) {
        let result = []; //
        let index = 0;
        return new MyPromise((resolve, reject) => {
          function addData (key, value) {
            result[key] = value;
            index++;
            // 如果都执行完，就返回结果
            if (index === array.length) {
              resolve(result);
            }
          }
          //
          for (let i = 0; i < array.length; i++) {
            let current = array[i];
            if (current instanceof MyPromise) {
              // promise 对象
              current.then(value => addData(i, value), reason => reject(reason))
            }else {
              // 普通值
              addData(i, array[i]);
            }
          }
        })
      }

      // 将给定的值，变成一个Promise对象
      static resolve (value) {
        //   instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
        if (value instanceof MyPromise) return value;
        return new MyPromise(resolve => resolve(value));
      }
    // finally 作用：无论最后是成功还是失败，都会执行
    //   不是类的对象
      finally (callback) {
        return this.then(value => {
          return MyPromise.resolve(callback()).then(() => value);
        }, reason => {
          return MyPromise.resolve(callback()).then(() => { throw reason })
        })
      }
       // catch 作用：用来最终处理失败的回调
      catch (failCallback) {
        return this.then(undefined, failCallback)
      }
}

function resolvePromise(promise2, x, resolve, reject) {
    // 防止对象循环调用
    if (promise2 === x) {
        reject(new TypeError('函数循环调用'))
    }
    if (x instanceof myPromise) {
        // promise 对象
        x.then(value => resolve(value), reason => reject(reason));
    } else {
        // 普通值
        resolve(x)

    }
}

// testAdmin

let promise = new myPromise((resolve, reject) => {
    // setTimeout(() => {

    //     resolve('成功')
    // }, 200)

    throw new Error('executor error')
    resolve('成功')
    // reject('失败')
})

// promise.then(value => {
//     console.log(value);

// }, reason => {
//     console.log(reason);

// })

// then 多次调用 
// 实现原理 ，将回调函数存储起来

// promise.then(value => {
//     console.log(1);
//     console.log(value);

// })
// promise.then(value => {
//     console.log(2);
//     console.log(value);

// })
// promise.then(value => {
//     console.log(3);
//     console.log(value);

// })

// // then 链式调用
//  let p1 = promise.then(value => {
//     // console.log(1);
//     console.log(value);
//     return p1;
// }).then(value=>{
//     console.log(value);

// })

// resolve 方法
//  let p1 = promise.then(value => {
//     // console.log(1);
//     console.log(value);
//     return p1;
// }).then(value=>{
//     console.log(value);

// })